home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / HackAddict™ Magazine / HA 1-12 / HackAddict01.sit / HackAddict ƒ / Files / ll.c < prev    next >
Text File  |  1996-02-21  |  15KB  |  608 lines

  1. /*=============================================================*\
  2.  * ll.c - link looker                                          *
  3.  * Copyright (C) 1994 by The Software System and lilo          *
  4.  * Written by George Shearer (george@sphinx.biosci.wayne.edu)  *
  5.  * Cleaned up to usability by lilo. :)                         *
  6.  *                                                             *
  7.  * September, 1994 - added help, version info and made the     *
  8.  *                   program so you can actually use it. :)    *
  9.  *                     --lilo                                  *
  10.  *                                                             *
  11.  * October 14, 1994 - cleaned up output flushing so you can    *
  12.  *                    actually watch in something like real    *
  13.  *                    time.  :)  --lilo                        *
  14.  *                                                             *
  15.  * October 28, 1994 - kill -1 will now produce a list of SPLIT *
  16.  *                    servers.           -Doc                  *
  17.  *                                                             *
  18.  * November 4, 1994 - should compile on non-POSIX systems now. *
  19.  *                    use -DHPSUCKS for HP-sUX systems 9.0x    *
  20.  * November 15, 1994 - fixed a small bug in lilo's -h checker  *
  21. \*=============================================================*/
  22.  
  23. /* This program is free software; you can redistribute it and/or modify
  24.  * it under the terms of the GNU General Public License as published by
  25.  * the Free Software Foundation; either version 2 of the License, or
  26.  * (at your option) any later version.
  27.  *
  28.  * This program is distributed in the hope that it will be useful,
  29.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31.  * GNU General Public License for more details.
  32.  *
  33.  * You should have received a copy of the GNU General Public License
  34.  * along with this program; if not, write to the Free Software
  35.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  36.  */
  37.  
  38. /* Compiling examples:
  39.  
  40.    regular old ANSI/C cc:
  41.    cc -O -s -o ll ll.c
  42.  
  43.    HP-UX cc:
  44.    cc +O3 -Aa -s -DHPSUCKS -o ll ll.c
  45.  
  46.    GNU GCC:
  47.  
  48.    Linux:
  49.      gcc -O2 -fomit-frame-pointer -funroll-loops -m486 -s -Wall -o ll ll.c
  50.  
  51.    BSD, SunOS 4.1.x, Slowaris 2.x, NeXT:
  52.      gcc -O2 -funroll-loops -s -Wall -o ll ll.c */
  53.  
  54. #define VERSION "1.06"
  55. #define BUFSIZE    400            /* IRC Server buffer */
  56. #define SERVER    "irc.escape.com"    /* IRC Server        */
  57. #define PORT    6667            /* IRC Port          */
  58. #define LDELAY    30            /* Loop delay seconds*/
  59. #define TIMEOUT    30            /* connection timeout*/
  60.  
  61. #define ESTABLISHED    1
  62. #define INPROGRESS    2
  63. #define SPLIT        1
  64.  
  65. #ifdef HPSUCKS
  66. #define _INCLUDE_HPUX_SOURCE
  67. #define _INCLUDE_XOPEN_SOURCE
  68. #define _INCLUDE_POSIX_SOURCE
  69. #endif
  70.  
  71. #include <sys/time.h>
  72. #include <stdio.h>
  73. #include <string.h>
  74. #include <stdlib.h>
  75. #include <unistd.h>
  76. #include <sys/types.h>
  77. #include <sys/socket.h>
  78. #include <fcntl.h>
  79. #include <signal.h>
  80. #include <errno.h>
  81. #include <netinet/in.h>
  82. #include <netdb.h>
  83. #include <arpa/inet.h>
  84. #include <pwd.h>
  85.  
  86. unsigned short int session=0,link_count=0;
  87. char in[BUFSIZE],out_buf[BUFSIZE],hostname[64];
  88. char *ins=in;
  89. char serverhost[81], nick[10], user[10], realname[81], lasttime[81];
  90. time_t ltime;
  91.  
  92. struct irc_server {
  93.   char *name;
  94.   char *link;
  95.   unsigned short int status;
  96.   time_t time;
  97.   struct irc_server *next;
  98. } *sl1=(struct irc_server *)0,*sl2=(struct irc_server *)0;
  99.  
  100. void do_ping(char *,char *);
  101. void do_001(char *,char *);
  102. void do_error(char *,char *);
  103. void do_364(char *,char *);
  104. void do_365(char *,char *);
  105.  
  106. /* prototyping is lame when the function is in the same
  107.    code, lilo outta just move the function before all
  108.    other functions that call it  :-) */
  109. char *stamp(time_t);
  110.  
  111. struct parsers {
  112.    char *cmd;
  113.    void (*func)(char *,char *);
  114. } parsefuns[] = {
  115.    { "PING", (void (*)())do_ping },
  116.    { "001", (void (*)())do_001 },
  117.    { "364",(void (*)())do_364 },
  118.    { "365", (void (*)())do_365},
  119.    { "ERROR",(void (*)())do_error},
  120.    { (char *)0,(void (*)())0 }
  121. };
  122.  
  123. struct sockaddr_in server;
  124. int sock=0;
  125.  
  126. #ifndef sys_errlist
  127. extern char *sys_errlist[];
  128. #endif
  129.  
  130. #ifndef errno
  131. extern int errno;
  132. #endif
  133.  
  134. char *
  135. mystrerror(int err) {
  136.   return(sys_errlist[err]);
  137. }
  138.  
  139. unsigned long int
  140. resolver(char *host) {
  141.   unsigned long int ip=0L;
  142.  
  143.   if(host && *host && (ip=inet_addr(host))==-1) {
  144.     struct hostent *he;
  145.     int x=0;
  146.  
  147.     while(!(he=gethostbyname((char *)host)) && x++<3) {
  148.       fprintf(stderr,"."); fflush(stderr);
  149.       sleep(1);
  150.     }
  151.     ip=(x<3) ? *(unsigned long *)he->h_addr_list[0] : 0L;
  152.   }
  153.  
  154.   return(ip);
  155. }
  156.  
  157. void
  158. clean_sl2(void) {
  159.   while(sl2) {
  160.     struct irc_server *temp=sl2->next;
  161.     if(sl2->name)
  162.       free(sl2->name);
  163.     if(sl2->link)
  164.       free(sl2->link);
  165.     free(sl2);
  166.     sl2=temp;
  167.   }
  168.   sl2=(struct irc_server *)0;
  169. }
  170.  
  171. void
  172. exit_program(char *why) {
  173.   fprintf(stderr,"\nExiting program. (%s)\n",why);
  174.  
  175.   if(sock)
  176.     close(sock);
  177.  
  178.   while(sl1) {
  179.     struct irc_server *temp=sl1->next;
  180.     if(sl1->name)
  181.       free(sl1->name);
  182.     if(sl1->link)
  183.       free(sl1->link);
  184.     free(sl1);
  185.     sl1=temp;
  186.   }
  187.  
  188.   clean_sl2();
  189.  
  190.   if(in)
  191.     free(in);
  192.  
  193.   exit(0);
  194. }
  195.  
  196. int mystrccmp(register char *s1,register char *s2) {
  197.    while((((*s1)>='a'&&(*s1)<='z')?(*s1)-32:*s1)==
  198.         (((*s2)>='a'&&(*s2)<='z')?(*s2++)-32:*s2++))
  199.      if(*s1++==0) return 0;
  200.    return (*(unsigned char *)s1-*(unsigned char *)--s2);
  201. }
  202.  
  203. char *mstrcpy(char **to,char *from) {
  204.   if(from) {
  205.     if((*to=(char *)malloc(strlen(from)+1)))
  206.       strcpy(*to,from);
  207.   }
  208.   else
  209.     *to=(char *)0;
  210.   return(*to);
  211. }
  212.  
  213. char *digtoken(char **string,char *match) {
  214.   if(string && *string && **string) {
  215.     while(**string && strchr(match,**string))
  216.       (*string)++;
  217.     if(**string) { /* got something */
  218.       char *token=*string;
  219.       if((*string=strpbrk(*string,match))) {
  220.         *(*string)++=(char)0;
  221.         while(**string && strchr(match,**string))
  222.           (*string)++;
  223.       }
  224.       else
  225.         *string = ""; /* must be at the end */
  226.       return(token);
  227.     }
  228.   }
  229.   return((char *)0);
  230. }
  231.  
  232. void signal_handler(void) {
  233.   exit_program("caught signal");
  234. }
  235.  
  236. void signal_alarm(void) {
  237.   exit_program("timed out waiting for server interaction.");
  238. }
  239.  
  240. void
  241. out(void) {
  242.   int length=strlen(out_buf);
  243.   errno=0;
  244.   if(write(sock,out_buf,length)!=length)
  245.     exit_program(mystrerror(errno));
  246. }
  247.  
  248. void
  249. init_server(void) {
  250.   int length;
  251.  
  252.   sprintf(out_buf,"USER %s %s %s :%s\nNICK %s\nMODE %s +is", \
  253.     user, user, user, realname, nick, nick);
  254.   length=strlen(out_buf);
  255.  
  256.   errno=0;
  257.  
  258.   if(write(sock,out_buf,length)==length) {
  259.     fputs("established\n",stderr);
  260.     session=ESTABLISHED;
  261.     alarm(TIMEOUT);
  262.     sprintf(out_buf,"LINKS\n");
  263.     out();
  264.   }
  265.   else
  266.     exit_program(mystrerror(errno));
  267. }
  268.  
  269. void
  270. heartbeat(void) {
  271.   strcpy(out_buf,"LINKS\n");
  272.   out();
  273.   signal(SIGALRM,(void (*)())heartbeat);
  274.   alarm(LDELAY);
  275. }
  276.  
  277. void
  278. do_364(char *from,char *left) {
  279.   struct irc_server *serv;
  280.   char *sv1,*sv2;
  281.   char *nick;
  282.  
  283.   serv=(struct irc_server *)malloc(sizeof(struct irc_server));
  284.   serv->next=sl2;
  285.  
  286.   serv->status=0;
  287.   nick=digtoken(&left," ");
  288.   sv1=digtoken(&left," ");
  289.   sv2=digtoken(&left," ");
  290.  
  291.   mstrcpy(&serv->name,sv1);
  292.   mstrcpy(&serv->link,sv2);
  293.   sl2=serv;
  294. }
  295.  
  296. int
  297. findserv(struct irc_server *serv,char *name) {
  298.   for(;serv;serv=serv->next)
  299.     if(!mystrccmp(name,serv->name))
  300.       return(1);
  301.   return(0);
  302. }
  303.  
  304. void
  305. show_split(void) {
  306.   struct irc_server *serv=sl1;
  307.  
  308.   signal(SIGHUP,(void (*)())show_split);
  309.   for(;serv;serv=serv->next) {
  310.     if(serv->status & SPLIT) {
  311.       printf("%s SPLIT: %s [%s]\n",stamp(serv->time),serv->name,serv->link);
  312.       fflush(stdout);
  313.     }
  314.   }
  315. }
  316.  
  317. void
  318. do_365(char *from,char *left) {
  319.   struct irc_server *serv=sl1;
  320.  
  321.   for(;serv;serv=serv->next) {
  322.     if(!findserv(sl2,serv->name)) {
  323.       if(!(serv->status & SPLIT)) {
  324.         serv->time=time(NULL);
  325.         printf("%s SPLIT: %s [%s]\n",stamp(serv->time),serv->name,serv->link);
  326.         fflush(stdout);
  327.         serv->status|=SPLIT;
  328.       }
  329.     }
  330.     else
  331.       if(serv->status & SPLIT) {
  332.         serv->time=time(NULL);
  333.         printf("%s MERGE: %s [%s]\n",stamp(serv->time),serv->name,serv->link);
  334.         fflush(stdout);
  335.         serv->status&=~SPLIT;
  336.       }
  337.   }
  338.  
  339.   serv=sl2;
  340.  
  341.   for(;serv;serv=serv->next) {
  342.     if(!findserv(sl1,serv->name)) {
  343.       struct irc_server *serv2;
  344.  
  345.       serv2=(struct irc_server *)malloc(sizeof(struct irc_server));
  346.       serv2->next=sl1;
  347.       serv2->status=0;
  348.       mstrcpy(&serv2->name,serv->name);
  349.       mstrcpy(&serv2->link,serv->link);
  350.       sl1=serv2;
  351.       serv2->time=time(NULL);
  352.       if(link_count) {
  353.         printf("%s ADDED: %s [%s]\n",stamp(serv2->time),serv->name,serv->link);
  354.         fflush(stdout);
  355.       }
  356.     }
  357.   }
  358.  
  359.   link_count=1;
  360.   clean_sl2();
  361. }
  362.  
  363. void
  364. do_ping(char *from,char *left) {
  365.   sprintf(out_buf,"PING :%s\n",hostname);
  366.   out();
  367. }
  368.  
  369. void
  370. do_001(char *from,char *left) {
  371.   fprintf(stderr,"Logged into server %s as nickname %s\n\n",from,nick);
  372.   fflush(stderr);
  373.   alarm(0);
  374.   signal(SIGALRM,(void (*)())heartbeat);
  375.   alarm(LDELAY);
  376. }
  377.  
  378. void
  379. do_error(char *from,char *left) {
  380.   fprintf(stderr,"Server error: %s\n",left);
  381.   fflush(stderr);
  382. }
  383.  
  384. void
  385. parse2(void) {
  386.   char *from,*cmd,*left;
  387.  
  388.   if(*ins==':') {
  389.     if(!(cmd=strchr(ins,' ')))
  390.       return;
  391.     *cmd++=(char)0;
  392.     from=ins+1;
  393.   }
  394.   else {
  395.     cmd=ins;
  396.     from=(char *)0;
  397.   }
  398.   if((left=strchr(cmd,' '))) {
  399.     int command;
  400.     *left++=(char)0;
  401.     left=(*left==':') ? left+1 : left;
  402.     for(command=0;parsefuns[command].cmd;command++) {
  403.       if(!mystrccmp(parsefuns[command].cmd,cmd)) {
  404.         parsefuns[command].func(from,left);
  405.         break;
  406.       }
  407.     }
  408.   }
  409. }
  410.  
  411. void
  412. parse(int length) {
  413.   char *s=in;
  414.  
  415.   *(ins+length)=(char)0;
  416.  
  417.   for(;;) {
  418.     ins=s;
  419.     while(*s && *s!=(char)13 && *s!=(char)10)
  420.       s++;
  421.     if(*s) {
  422.       while(*s && (*s==(char)13 || *s==(char)10))
  423.         *s++=(char)0;
  424.       parse2();
  425.     }
  426.     else
  427.       break;
  428.   }
  429.   strcpy(in,ins);
  430.   ins=in+(s-ins);
  431. }
  432.  
  433. void
  434. process_server(void) {
  435.   int x=0;
  436.  
  437.   for(;;) {
  438.     fd_set rd,wr;
  439.     struct timeval timeout;
  440.  
  441.     timeout.tv_usec=0; timeout.tv_sec=1;
  442.     FD_ZERO(&rd); FD_ZERO(&wr);
  443.  
  444.     FD_SET(sock,&rd);
  445.     if(session==INPROGRESS)
  446.       FD_SET(sock,&wr);
  447.  
  448.     errno=0;
  449.  
  450. #ifdef HPSUCKS
  451.     select((size_t)FD_SETSIZE,(int *)&rd,(int *)&wr,(int *)0,(session==INPROGRESS)?(const struct timeval *)&timeout:(const struct timeval *)0);
  452. #else
  453.     select(getdtablesize(),(fd_set *)&rd,(fd_set *)&wr,(fd_set *)0,(session==INPROGRESS)?(struct timeval *)&timeout:(struct timeval *)0);
  454. #endif
  455.  
  456.     if(errno==EINTR)
  457.       continue;
  458.  
  459.     errno=0;
  460.     if(session==INPROGRESS) {
  461.       if(FD_ISSET(sock,&wr)) {
  462.         init_server();
  463.          continue;
  464.       }
  465.       else {
  466.         if(x++>=TIMEOUT)
  467.           exit_program("connection timed out");
  468.         fprintf(stderr,"."); fflush(stderr);
  469.       }
  470.     }
  471.  
  472.     if(FD_ISSET(sock,&rd)) {
  473.       int length=read(sock,ins,BUFSIZE-(ins-in));
  474.  
  475.       if(length<1) {
  476.         if(session!=INPROGRESS) {
  477.           if(!errno) {
  478.             fputs("Connection closed by foreign host.",stderr);
  479.             errno=ENOTCONN;
  480.           }
  481.           else
  482.             fprintf(stderr,"Connection to %s closed.\n",
  483.                    inet_ntoa(server.sin_addr));
  484.           fflush(stderr);
  485.         }
  486.         exit_program(mystrerror(errno));
  487.       }
  488.       if(strpbrk(in,"\x0a\x0d"))
  489.         parse(length);
  490.       else
  491.         ins=(BUFSIZE-((ins+length)-in)<1)?in:ins+length;
  492.     }
  493.   }
  494. }
  495.  
  496. char *stamp(time_t ltime) {
  497.   strftime(lasttime, 81, "%x %X", localtime(<ime));
  498.   return (char *) &lasttime;
  499. }
  500.  
  501. void
  502. main(int argc,char *argv[]) {
  503.   unsigned short int sport=PORT;
  504.   unsigned int loop;
  505.   struct passwd *passent;
  506.   
  507.   fprintf(stderr, "Link Looker v%s, written and designed by Dr. Delete.\n" \
  508.                   "                   Enhanced by lilo.\n" \
  509.                   "Type '%s -h' or '%s --help' for more information.\n\n",
  510.     VERSION, argv[0], argv[0]);
  511.     
  512.   for(loop=1; loop<argc; loop++) {
  513.     if(!strcmp("-h", argv[loop]) || !strcmp("--help", argv[loop])) {
  514.         fprintf(stderr,"Format:\n\n" \
  515.         "  %s [-h] [<nick> [<server>[:<port>] ['<real name field>' " \
  516.         "[<username>]]]]\n\n  where:\n\n" \
  517.         "  <nick>            is the nickname to be used (default is userid),\n" \
  518.         "  <server>          is the hostname of the server to be used,\n" \
  519.         "  <port>            is a four digit port number (default is 6667),\n" \
  520.         "  <real name field> is a description of the user (default is gecos info), and\n" \
  521.         "  <username>        is the user account field, used only if identd\n" \
  522.         "                    has not been enabled on the user's system.\n", \
  523.         argv[0]);
  524.       exit(1);
  525.     }
  526.   }
  527.   
  528.   passent=getpwuid(getuid());
  529.  
  530.   if(argc>1)
  531.     strncpy(nick,argv[1],9);
  532.   else
  533.     strncpy(nick,passent->pw_name,9);
  534.  
  535.   if(argc>2) {
  536.     char *port=strchr(argv[2],':');
  537.     sport=(port)?atoi(port+1):sport;
  538.     strncpy(serverhost,argv[2],80);
  539.     if(port)
  540.       serverhost[port-argv[2]]=(char)0;
  541.   }
  542.   else
  543.     strncpy(serverhost,SERVER,80);
  544.     
  545.   if(argc>3)
  546.     strncpy(realname,argv[3],80);
  547.   else {
  548.     char *comma=strchr(passent->pw_gecos,',');
  549.     strncpy(realname,passent->pw_gecos,80);
  550.     if(comma)
  551.       realname[comma-(passent->pw_gecos)]=(char)0;
  552.   }
  553.  
  554.   if(argc>4)
  555.     strncpy(user,argv[4],9);
  556.   else
  557.     strncpy(user,passent->pw_name,9);
  558.  
  559.   signal(SIGPIPE,(void (*)())signal_handler);
  560.   signal(SIGHUP,(void (*)())show_split);
  561.   signal(SIGINT,(void (*)())signal_handler);
  562.   signal(SIGTERM,(void (*)())signal_handler);
  563.   signal(SIGBUS,(void (*)())signal_handler);
  564.   signal(SIGABRT,(void (*)())signal_handler);
  565.   signal(SIGSEGV,(void (*)())signal_handler);
  566.   signal(SIGALRM,(void (*)())signal_alarm);
  567.  
  568.   errno=0;
  569.   if((sock=socket(AF_INET,SOCK_STREAM,0))>0) {
  570.     server.sin_family=AF_INET;
  571.     server.sin_port=htons(sport);
  572.     fprintf(stderr,"Resolving %s...",serverhost); fflush(stderr);
  573.     if((server.sin_addr.s_addr=resolver(serverhost))) {
  574.       fputs("done\n",stderr);
  575.       fflush(stderr);
  576.  
  577.       setsockopt(sock,SOL_SOCKET,SO_LINGER,0,0);
  578.       setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,0,0);
  579.       setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,0,0);
  580.  
  581.       fcntl(sock,F_SETFL,(fcntl(sock,F_GETFL)|O_NDELAY));
  582.  
  583.       fprintf(stderr,"Connecting to %s...",inet_ntoa(server.sin_addr));
  584.       fflush(stderr);
  585.  
  586.       errno=0;
  587.       if(connect(sock,(struct sockaddr *)&server,sizeof(server))) {
  588.         if(errno!=EINPROGRESS && errno!=EWOULDBLOCK)
  589.           exit_program(mystrerror(errno));
  590.         else
  591.           session=INPROGRESS;
  592.       }
  593.       else
  594.         init_server();
  595.  
  596.       gethostname(hostname,64);
  597.       process_server();
  598.     }
  599.     else
  600.       exit_program("resolve failed");
  601.   }
  602.   else {
  603.     fprintf(stderr,"Failed to allocate an AF_INET socket. (%s)\n", \
  604.       mystrerror(errno));
  605.     fflush(stderr);
  606.   }
  607. }
  608.